package com.steven.pipe;

import com.steven.container.Contained;
import com.steven.container.Container;
import com.steven.lifecycle.Lifecycle;
import com.steven.task.Task;
import com.steven.value.Value;
import com.steven.value.ValueContext;

public class SimplePipeline implements Pipeline, Lifecycle {
	
	// The basic Valve (if any) associated with this Pipeline.
	protected Value basic = null;
	// The Container with which this Pipeline is associated.
	protected Container container = null;
	// the array of Valves
	protected Value values[] = new Value[0];	
	
	  
	public SimplePipeline(Container container) {
		    setContainer(container);
		  
	}
	  
	public void setContainer(Container container) {
		    this.container = container;
	}	
	
	@Override
	public void addValue(Value value) {
		
	 if (value instanceof Contained)
	        ((Contained) value).setContainer(this.container);
	 
		synchronized(values){
			Value results[]=new Value[values.length+1];
			System.arraycopy(values, 0, results, 0,values.length);
			results[values.length]=value;
			values=results;
		}
	}

	@Override
	public Value getBasic() {
		return basic;
	}

	@Override
	public Value[] getValues() {
		return values;
	}

	@Override
	public void invoke(Task task) {
		 (new StandardPipelineValveContext()).invokeNext(task);
	}

	@Override
	public void removeValue(Value value) {
		
	}

	@Override
	public void setBasic(Value value) {
	    this.basic = value;
	    ((Contained) value).setContainer(container);
	}

	@Override
	public void start() {
		
	}

	@Override
	public void stop() {
		
	}
	
	protected class StandardPipelineValveContext implements ValueContext {
	    protected int stage = 0;
	    public String getInfo() {
	      return null;
	    }

	    public void invokeNext(Task task){
	      int subscript = stage;
	      stage = stage + 1;
	      // Invoke the requested Valve for the current request thread
	      if (subscript < values.length) {
	        values[subscript].invoke(task,this);
	      }
	      else if ((subscript == values.length) && (basic != null)) {
	        basic.invoke(task,this);
	      }
	      else {
	        
	      }
	    }
	  } // end of inner class

}
